#include "RxFIFO.h"

can_message_t canRxBuffer[CAN_RXBUFFER_SIZE];
RxFIFOCtrl_t RxFIFOCtrl = {
    .BufferSize = CAN_RXBUFFER_SIZE,
    .pBuffer = canRxBuffer
};

void CAN_RxInterrupt(void)
{
    can_message_t can_message_rx;
    // can_message_rx.id = ;
    // can_message_rx.dlc = l
    // can_message_rx.data = ;
    pushRxFIFO(can_message_rx);
}

/**
  * @brief  Add a message to the FIFO to the data buffer
  * @param  can_message_t message
  * @retval None
  * @note   None
*/
void pushRxFIFO(can_message_t can_message)
{
    NVIC_INTERRPUT_DISABLE;

    memcpy(&RxFIFOCtrl.pBuffer[RxFIFOCtrl.WriteIndex], &can_message, sizeof(can_message_t));

    RxFIFOCtrl.WriteIndex += 1;
    
    RxFIFOCtrl.WriteIndex = RxFIFOCtrl.WriteIndex & (RxFIFOCtrl.BufferSize - 1);

    if(RxFIFOCtrl.WriteIndex == RxFIFOCtrl.ReadIndex){
        RxFIFOCtrl.ReadIndex += 1;
        RxFIFOCtrl.ReadIndex = RxFIFOCtrl.ReadIndex & (RxFIFOCtrl.BufferSize - 1);
    }else{
        RxFIFOCtrl.GotMsgNum++;
    }

    NVIC_INTERRPUT_ENABLE;
}

/**
  * @brief  Read a message from the FIFO to the data buffer
  * @param  can_message_t** Message pointer
  * @param  msglen Gets the number of message frames
  * @retval The number of actually obtained CAN message frames
  * @note   None
*/
int32_t popRxFIFO(can_message_t **can_message, uint8_t msglen)
{
    NVIC_INTERRPUT_DISABLE;

    int32_t msg_num = ((RxFIFOCtrl.WriteIndex >= RxFIFOCtrl.ReadIndex) ? RxFIFOCtrl.GotMsgNum : (RxFIFOCtrl.BufferSize - RxFIFOCtrl.ReadIndex));

    *can_message = &RxFIFOCtrl.pBuffer[RxFIFOCtrl.ReadIndex];

    msg_num = (msg_num < msglen) ? msg_num : msglen;
    RxFIFOCtrl.GotMsgNum -= msg_num;
    RxFIFOCtrl.ReadIndex = (RxFIFOCtrl.ReadIndex+msg_num) & (RxFIFOCtrl.BufferSize - 1);

    NVIC_INTERRPUT_ENABLE;
    return msg_num;
}

/* use example
while(1) {
    can_message_t *can_message;
    if(popRxFIFO(&can_message, 1)) {
        // user handle begin
        // can_send(can_message);
        // user handle begin
    }
}
*/
